var DetlefSchneider = function() {
    var loading_icon = STATIC_URL + 'bin/loader.gif';

    var min_width = 473;

    var max_width = 1010;

    var max_height = 643;

    var image_opacity = 0.2;

    var image_opacity_hover = 0.5;

    var down_arrow_disabled = ['iPad'];

    function init() {
        $(document.body).removeClass('no-js').addClass('js');

        attachContentWidthResizer();
        catchDeepLinks();
        attachCarouselOpeners();
        attachDownButton();
        attachImageFaders();
        attachImageHovers();
        attachGalleryGridHovers();
        attachDownArrowDisabler();

        // Preload loading image
        img = new Image();
        img.src = loading_icon;

        // Trigger a resize after the assets have loaded and when devices are
        // rotated to ensure everything is sized correctly
        $(window).bind('load onorientationchange', function () {
            $(window).resize();
        })
    }

    function attachContentWidthResizer() {
        $(window).resize(function() {
            $('.content').css({
                'width': 'auto'
            })

            if (isMobileView()) {
                var column_width = $(window).width();
            } else {
                var nav_width = $('nav.global').outerWidth();
                var window_width = $(document).width();
                var right_gutter_width = $('.gutter').outerWidth();

                var column_width = window_width - nav_width
                        - right_gutter_width;

                if (column_width > max_width) {
                    column_width = max_width;
                } else if (column_width < min_width) {
                    column_width = min_width;
                }
            }

            $('.content').width(column_width);

            positionGutter();

            // Lagging this by 100ms seems to be enough
            // time for the $(document).height() call
            // to pick up the new document height..
            setTimeout(function() {
                resize100PercentColumnHeights();
                resizeItems();
            }, 100);
        }).resize();
    }

    function resize100PercentColumnHeights() {
        if (!isMobileView()) {
            $('.h100').height($(document).height());
        } else {
            $('.h100').css({
                'height': 'auto'
            });
        }
    }

    function positionGutter() {
        var content_edge = $('.content').offset().left +
            $('.content').outerWidth();
        var window_width = $(window).width();
        var gutter_width = $('.gutter').outerWidth();

        var right_value = window_width - content_edge -
            gutter_width;

        $('.gutter').css({
            'right': right_value + 'px'
        });
    }

    function resizeItems() {
        var width = $('.gallery').outerWidth();
        var ratio = max_width / max_height;
        var elementHeight = Math.round((width / ratio), 10);
        var halfWidth = Math.round((width / 2), 10);
        var halfHeight = Math.round((elementHeight / 2), 10);

        $('.video-player.item-100').attr('width', width).attr('height', elementHeight);
        $('.video-player.item-50').attr('width', halfWidth).attr('height', halfHeight);
        $('.cover.item-100').css({
            'width': width + 'px',
            'height': elementHeight + 'px'
        });
        $('.cover.item-50').css({
            'width': halfWidth + 'px',
            'height': halfHeight + 'px'
        })
    }

    function catchDeepLinks() {
        $.address.change(function(event) {
            var pattern = /^(\/gallery\/[a-zA-Z0-9_-]+\/)(([a-zA-Z0-9_-]+)\/([a-zA-Z0-9_.-]+))?$/
            var urlParts = event.value.match(pattern);

            if (urlParts == null) {
                // URL is not matched. Don't do anything with it.
                return false;
            }

            var type = urlParts[3];
            var id = urlParts[4];

            if (!carouselOpen(urlParts[1])) {
                // Open carousel, then try to load in gallery image
                openCarousel(urlParts[1], function() {
                    openGallery(type, id);
                });
            } else if (urlParts[2] != undefined) {
                // Carousel is already open, so just load in gallery image
                openGallery(type, id);
            }
        });
    }

    function attachCarouselOpeners() {
        $('a[rel~="gallery"]').click(function() {
            // Don't use carousel on mobile view
            if (isMobileView()) {
                return true;
            }

            if (carouselOpen($(this).attr('href'))) {
                // Move to the next item in the carousel
                var currentCarouselItem = $(this).next('.carousel-wrapper')
                    .find('.carousel .active').parents('li').first();
                currentCarouselItem.next().find('a').click();

                if (currentCarouselItem.next().index() > 0) {
                    $('.carousel').jcarousel('scroll', currentCarouselItem.next().index());
                }
            } else {
                $.address.value($(this).attr('href'));
            }

            return false;
        });
    }

    function openCarousel(url, callback) {
        caller = getLinkFromUrl(url);

        showLoadingGraphic(caller);

        $(caller).find('img').animate({
            'opacity': 1
        }, 500).addClass('active');
        $(caller).find('figcaption').hide();

        $.get(url, function(response) {
            $(caller).after(response);
            attachGalleryOpeners();
            carouselElement = $(caller).parent().find('.carousel-wrapper');

            if (carouselElement.find('li').length > 1) {
                carouselElement.animate({
                    'height': 157
                }, 500, function() {
                    scrollToTopOfElement(caller);
                    playVideo(carouselElement);
                });
            } else {
                scrollToTopOfElement(caller);
                playVideo(carouselElement);
            }

            hideLoadingGraphic(caller);

            if (typeof(callback) == 'function') {
                callback();
            }

            attachCarousel();
            attachImageFaders();
        });
    }

    function scrollToTopOfElement(caller) {
        // Scroll to top of window
        $('html, body').animate({
            scrollTop: $(caller).find('img:first').offset().top
        }, 300);
        $(window).resize();
    }

    function playVideo(carousel) {
        var link = carousel.find('a:first');

        if (link.attr('rel') && link.attr('rel').indexOf('video') > -1) {
            $(link).click();
        }
    }

    function closeOpenCarousel(url, callback) {
        if (!existingCarousels()) {
            return false;
        }

        var container = $('.carousel').parents('.cover-item');

        $(container).find('img').animate({
            'opacity': image_opacity
        }, 500).removeClass('active');
        $(container).find('figcaption').show();

        $('.carousel-wrapper').animate({
            height: 0
        }, 500, function() {
            $('.carousel-wrapper').remove();

            // If we haven't just closed the thing we're trying
            // to open; open it
            if (url) {
                openCarousel(url, callback);
            }
        });
    }

    function getLinkFromUrl(url) {
        return $('a[href*="'+url+'"]');
    }

    function getFileFromUrl(url) {
        var pattern = /\/([^\/]+)$/
        matches = url.match(pattern);

        if (matches.length > 0) {
            return matches[1];
        }

        return false;
    }

    function carouselOpen(url) {
        var link = getLinkFromUrl(url);
        return (link.find('img.active').length > 0);
    }

    function attachCarousel() {
        $('.carousel').jcarousel({
            buttonNextHTML: null,
            buttonPrevHTML: null,
            circular: false,
            scroll: 2,
            easing: 'linear',
            animation: 200,
            itemFallbackDimension: 157,
            initCallback: function(carousel) {
                $('.carousel-next').bind('click', function() {
                    carousel.next();
                    return false;
                });

                $('.carousel-prev').bind('click', function() {
                    carousel.prev();
                    return false;
                })
            },
            buttonNextCallback: function (carousel, button, state) {
                var carouselContainer = carousel.container
                    .parents('.carousel-wrapper').find('.carousel-nav');

                if (state) {
                    carouselContainer.find('.carousel-next').removeClass('disabled');
                } else {
                    carouselContainer.find('.carousel-next').addClass('disabled');
                }
            },
            buttonPrevCallback: function (carousel, button, state) {
                var carouselContainer = carousel.container
                    .parents('.carousel-wrapper').find('.carousel-nav');

                if (state) {
                    carouselContainer.find('.carousel-prev').removeClass('disabled');
                } else {
                    carouselContainer.find('.carousel-prev').addClass('disabled');
                }
            },
            setupCallback: hideGalleryNav,
            reloadCallback: hideGalleryNav
        });
    }

    function hideGalleryNav(carousel) {
        var carouselContainer = carousel.container
            .parents('.carousel-wrapper').find('.carousel-nav');

        var prevButton = carouselContainer.find('.carousel-prev'),
            nextButton = carouselContainer.find('.carousel-next');

        setTimeout(function () {
            if (nextButton.hasClass('disabled') && prevButton.hasClass('disabled')) {
                carouselContainer.hide();
            } else {
                carouselContainer.show();
            }
        }, 100);
    }

    function attachGalleryOpeners() {
        $('.carousel a').click(function() {
            var fileName;

            if ($(this).attr('href').indexOf('vimeo.com') > 0) {
                fileName = getVideoUrl($(this).attr('href'));
            } else {
                fileName = getImageUrl($(this).attr('href'))
            }

            $.address.value(getBaseUrl() + fileName);

            return false;
        });
    }

    function getImageUrl(url) {
        fileName = getFileFromUrl(url);

        return 'image/' + fileName;
    }

    function getVideoUrl(url) {
        var regex = /vimeo.com\/([0-9]+)/;
        var matches = regex.exec(url);

        if (matches.length > 1) {
            return 'video/' + matches[1];
        }

        return false;
    }

    function getBaseUrl() {
        var currentUrl = new String($.address.value());
        var regex = /^(\/gallery\/[a-zA-Z0-9-_]+\/)/;

        var matches = regex.exec(currentUrl);

        if (matches.length > 1) {
            return matches[1];
        }

        return false;
    }

    function openGallery(type, item) {
        var activeLink = getLinkFromUrl(item);
        if (activeLink.length < 1 || item.length < 1) {
            return false;
        }

        // Switch opaque item overlay to mark current active
        $(activeLink).parents('.carousel').find('img').css({
            'opacity': image_opacity
        }).removeClass('active');
        $(activeLink).find('img').stop().animate({
            'opacity': 1
        }, 0).addClass('active');

        var target = $(activeLink).attr('href');
        var container = $(activeLink).parents('.cover-item')
                                    .find('a[rel~="gallery"]');

        switch (type) {
        case 'image':
            switchImage(container, target, activeLink, item);
            break;
        case 'video':
            switchVideo(container, item);
            break;
        }
    }

    function switchImage(container, target, activeLink, image) {
        // Only switch out the image if it's not the same
        if ($(container).find('img').length > 0 &&
            $(container).find('img').attr('src') ==
                $(activeLink).attr('href')) {
            return false;
        }

        showLoadingGraphic(container);

        // Preload the new image
        var new_image = new Image();
        new_image.onload = function() {
            // When it's loaded remove the loading graphic
            hideLoadingGraphic(container);

            if ($(container).find('img').length > 0) {
                // Crossfade the old and new images
                $(container).find('img').animate({
                    'opacity': 0
                }, function() {
                    $(container).find('img')
                        .attr('src', target).animate({
                            'opacity': 1
                        }, function () {
                            resizeItems();
                            $.scrollTo({ top: $(container).offset().top, left: 0 }, 0);
                        }
                    );
                });
            }

            resizeItems();
            $.scrollTo({ top: $(container).offset().top, left: 0 }, 0);

            $(container).find('iframe').remove();
        };
        new_image.src = $(activeLink).attr('href');
    }

    function switchVideo(container, video) {
        var embed = '<iframe src="//player.vimeo.com/video/' +
            video + '?color=aaddee&autoplay=true" width="500" height="281" ' +
            'frameborder="0" class="video-player item-100" webkitAllowFullScreen ' +
            'mozallowfullscreen allowFullScreen></iframe>';

        var existingIframe = $(container).find('iframe');

        $(container).find('img:first').after(embed);

        existingIframe.remove();
        $(container).find('img').attr('src', '').hide();

        resizeItems();

        $.scrollTo({ top: $(container).find('iframe').offset().top, left: 0 }, 0);
    }

    function attachDownButton() {
        $('.down-arrow').click(function() {
            var top = $(window).scrollTop();

            // Iterate through each item in the set
            $('.cover-item').each(function(i, el) {
                // When we find the first item that is not above the top
                // of the page, scroll to it.
                if ($(el).offset().top > top) {
                    $.scrollTo($(el), 500);

                    return false;
                }
            });

            return false;
        });
    }

    function attachImageFaders() {
        $('img').one('load', function() {
            if (!$(this).hasClass('faded')) {
                var opacity = image_opacity;
                if ($(this).hasClass('active')) {
                    opacity = 1;
                }

                $(this).animate({
                    'opacity': opacity
                }, 1000);
                $(this).addClass('faded');
            }
        }).each(function() {
            if (this.complete) {
                $('img').load();
            }
        });
    }

    function attachImageHovers() {
        $('.gallery-list a, ' +
          '.gallery-grid a').live('mouseover', function() {
            var img = $(this).find('img');
            if (img.hasClass('faded')) {
                if (!$(img).hasClass('active')) {
                    $(img).stop().animate({
                        'opacity': image_opacity_hover
                    }, 500);
                }
            }
        }).live('mouseout', function() {
            var img = $(this).find('img');
            if (!$(img).hasClass('active')) {
                $(img).stop().animate({
                   'opacity': image_opacity
                }, 500);
            }
        });
    }

    function attachGalleryGridHovers() {
        $('.gallery-grid a').bind('mouseover mouseout', function () {
            $(this).find('figcaption').toggle();
        });
    }

    function attachDownArrowDisabler() {
        if (deviceMatch(down_arrow_disabled)) {
            $('.down-arrow').remove();
        }
    }

    function deviceMatch(devices) {
        for (var i = 0; i < devices.length; i++) {
            var regex = new RegExp(devices[i], 'i');
            if (navigator.userAgent.match(regex)) {
                return true;
            }
        }

        return false;
    }

    function showLoadingGraphic(container) {
        loading_img = new Image();
        loading_img.src = loading_icon;
        loading_img.className = 'loader';

        $(container).append(loading_img);
    }

    function hideLoadingGraphic(container) {
        $(container).find('.loader').remove();
    }

    function existingCarousels() {
        return ($('.carousel').length > 0);
    }

    function isMobileView() {
        return $(window).width() <= 767;
    }

    return {
        init: init
    }
}();

DetlefSchneider.init();